package com.gaokuo.es.compose;

import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;

import java.util.concurrent.TimeUnit;

/**
 * 根据默认规则将节点转化为查询体
 * 默认规则  条件之间按照从前到后一个一个计算
 * @author gaokuo
 */
public class DefaultEsComposeSearch implements IEsComposeSearch{
    private final DefaultConditionBuild conditionBuild;

    public DefaultEsComposeSearch(DefaultConditionBuild conditionBuild) {
        this.conditionBuild = conditionBuild;
    }
    @Override
    public String getBoolQueryStr(ComposeNestedNode composeNode) {
        return getBoolQuery(composeNode).toString();
    }
    @Override
    public BoolQueryBuilder getBoolQuery(ComposeNestedNode composeNode) {
        return dealNestedNode(composeNode);
    }

    /**
     * 递归处理嵌套节点
     * @param node ~
     * @return BoolQueryBuilder
     */
    private BoolQueryBuilder dealNestedNode(ComposeNestedNode node){
        AbComposeNode focus = node.childNode();
        BoolQueryBuilder boolQueryBuilder = getBoolQueryBuilder();
        if(focus == null){
            return boolQueryBuilder;
        }
        do{
            BoolQueryBuilder oldBoolQueryBuilder = boolQueryBuilder;
            QueryBuilder item;
            if(focus instanceof ComposeNestedNode){
                item = dealNestedNode((ComposeNestedNode) focus);
            }else{
                item = conditionBuild.getQueryBuilder((ComposeConditionNode) focus);
            }
            if(focus.bind == ComposeBindEnum.or){
                boolQueryBuilder = getBoolQueryBuilder();
                boolQueryBuilder.should(oldBoolQueryBuilder).should(item);
            }else{
                boolQueryBuilder.must(item);
            }
        }while ((focus = focus.next) != null);
        return boolQueryBuilder;
    }

    /**
     * 获取boolQuery
     * 1.minimum_should_match设置为0
     * @return ~
     */
    private static BoolQueryBuilder getBoolQueryBuilder(){
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        boolQuery.minimumShouldMatch(1);
        return boolQuery;
    }

    public static void main(String[] args) throws InterruptedException {

        ComposeConditionNode conditionNode1 = new ComposeConditionNode("name",ConditionEnum.term,"p1");
        ComposeConditionNode conditionNode2 = new ComposeConditionNode(ComposeBindEnum.or,"age",ConditionEnum.gte,"21");
        ComposeConditionNode conditionNode3 = new ComposeConditionNode("age",ConditionEnum.lt,"50");
        ComposeConditionNode conditionNode4 = new ComposeConditionNode(ComposeBindEnum.and,"sex",ConditionEnum.term,"女");
        ComposeConditionNode conditionNode5 = new ComposeConditionNode(ComposeBindEnum.and,"say",ConditionEnum.match,"1");

        ComposeNestedNode composeNestedNode1 = new ComposeNestedNode();
        composeNestedNode1.addChildNode(conditionNode1).addChildNode(conditionNode2);
        ComposeNestedNode composeNestedNode2 = new ComposeNestedNode(ComposeBindEnum.or);
        composeNestedNode2.addChildNode(conditionNode3).addChildNode(conditionNode4);

        ComposeNestedNode composeNestedNode = new ComposeNestedNode(ComposeBindEnum.and);
        composeNestedNode.addChildNode(composeNestedNode1);
        composeNestedNode.addChildNode(conditionNode5);
        composeNestedNode.addChildNode(composeNestedNode2);


        DefaultEsComposeSearch composeSearch = new DefaultEsComposeSearch(new DefaultConditionBuild());

        System.out.println(composeSearch.getBoolQueryStr(composeNestedNode));
        TimeUnit.SECONDS.sleep(1);
    }

}
